package org.hxzon.tapestry5.util;

import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletResponse;

import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.internal.services.PageResponseRenderer;
import org.apache.tapestry5.internal.services.RequestPageCache;
import org.apache.tapestry5.internal.services.ServicesMessages;
import org.apache.tapestry5.internal.structure.Page;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.services.ExceptionReporter;
import org.apache.tapestry5.services.RequestExceptionHandler;
import org.apache.tapestry5.services.Response;
import org.slf4j.Logger;

public class MyRequestExceptionHandler implements RequestExceptionHandler {
    private final RequestPageCache pageCache;

    private final PageResponseRenderer renderer;

    private final Logger logger;

    private final String pageName;

    private final Response response;

    private final boolean productionMode;

    public MyRequestExceptionHandler(RequestPageCache pageCache, PageResponseRenderer renderer, Logger logger,

    @Symbol(SymbolConstants.EXCEPTION_REPORT_PAGE) String pageName,

    Response response, @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode) {
        this.pageCache = pageCache;
        this.renderer = renderer;
        this.logger = logger;
        this.pageName = pageName;
        this.response = response;
        this.productionMode = productionMode;
    }

    public void handleRequestException(Throwable exception) throws IOException {
        logger.error(ServicesMessages.requestException(exception), exception);

        // TAP5-233: Make sure the client knows that an error occurred.

        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

        if (!productionMode) {
            String rawMessage = InternalUtils.toMessage(exception);

            // Encode it compatibly with the JavaScript escape() function.

            String encoded = URLEncoder.encode(rawMessage, "UTF-8").replace("+", "%20");

            response.setHeader("X-Tapestry-ErrorMessage", encoded);

            Page page = pageCache.get(pageName);

            ExceptionReporter rootComponent = (ExceptionReporter) page.getRootComponent();

            // Let the page set up for the new exception.

            rootComponent.reportException(exception);

            renderer.renderPageResponse(page);
        } else {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "服务器运行出错");
        }
    }
}